package com.ptms.service;

import com.ptms.entity.User;
import com.ptms.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Collections;

/**
 * 适配JPA的UserDetailsService实现：
 * 核心：调用UserRepository（Spring Data JPA）查询用户，封装角色权限给Spring Security
 */
@Service // 标注为Spring Service，让Security自动识别
@Slf4j // Lombok日志，替代System.out
@RequiredArgsConstructor // 构造器注入（避免@Autowired，符合Spring最佳实践）
public class UserDetailsServiceImpl implements UserDetailsService {

    // 注入你原有的UserRepository（Spring Data JPA），直接复用查询能力
    private  final UserRepository userRepository;

    /**
     * Spring Security认证核心方法：根据用户名名加载用户
     * @param username 前端传入的登录用户名
     * @return 封装好角色权限的UserDetails对象
     * @throws UsernameNotFoundException 用户名不存在时抛出（Security自动处理为认证失败）
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 调用原有UserRepository的findByUsername方法查用户（JPA的Optional需用orElseThrow处理空值）
        User dbUser = userRepository.findByUsername(username)
                .orElseThrow(() -> {
                    log.error("认证失败：用户名[{}]不存在", username);
                    // 抛出Security标准异常，后续会自动转为401/认证失败响应
                    return new UsernameNotFoundException("user '" + username + "' not found");
                });

        // 2. 封装角色权限：Spring Security要求角色格式为「ROLE_角色名」（如ROLE_admin）
        // 注意：dbUser.getUserType()是你数据库存储的角色（如admin/student），需拼接前缀
        SimpleGrantedAuthority userAuthority = new SimpleGrantedAuthority("ROLE_" + dbUser.getUserType());

        // 3. 封装为Security的UserDetails对象（返回给过滤器/权限校验器）
        // 参数说明：用户名、加密密码、账号否启用、是否过期、密码是否过期、是否锁定、角色列表
        return new org.springframework.security.core.userdetails.User(
                dbUser.getUsername(),          // 数据库中的用户名（用于认证用）
                dbUser.getPassword(),          // 数据库中的加密密密码（必须是BCrypt等加密后的字符串）
                true,                          // 账号是否启用（业务中可加字段控制，如is_enabled）
                true,                          // 账号是否过期（业务中可加字段控制）
                true,                          // 密码是否过期（业务中可加字段控制）
                true,                          // 账号是否锁定（业务中可加字段控制）
                Collections.singletonList(userAuthority) // 角色列表（单个角色用singletonList，多个用Arrays.asList）
        );
    }
}
